package org.xjc.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.xjc.config.RequestVariable;
import org.xjc.annotation.Error;
import org.xjc.service.ErrorLogService;
import org.xjc.vo.RespBean;
import org.xjc.vo.RespPageBean;
import org.xjc.exception.CustomException;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author : XJC
 * @Description : Error aop
 * @create : 2022/7/25 17:33
 */
@Order(1)
@Aspect
@Component
public class ErrorAspect {

    @Resource
    ErrorLogService errorLogService;

    public ErrorAspect() {
    }

    @Pointcut("@annotation(org.xjc.annotation.Error)")
    public void errorAspect() {
    }

    @Around("errorAspect()")
    public Object doAround(ProceedingJoinPoint joinPoint) {
        Error error = null;

        try {
            try {
                error = getErrorData(joinPoint);
            } catch (Exception var5) {
                var5.printStackTrace();
            }

            Object data = joinPoint.proceed();
            if (data == null) {
                return RespBean.success("操作成功");
            } else if (data instanceof RespBean || data instanceof RespPageBean) {
                return data;
            } else {
                return RespBean.success("操作成功", data);
            }
        } catch (Throwable var6) {
            if (error != null) {
                //能获取到Error注解，包装返回信息
                if (var6.getClass() == error.exception()) {
                    //Error注释中包含这个Exception，返回该错误的Msg，
                    if (var6 instanceof CustomException) {
                        //默认为CustomException
                        CustomException customException = (CustomException) var6;
                        return RespBean.error(customException.getMsg());
                    } else {
                        return RespBean.error(var6.getMessage());
                    }
                } else {
                    System.out.println("{}===============>错误信息");
                    var6.printStackTrace();
                    //返回Error注释中的Msg信息
                    saveErrorLog(var6, error.description(), joinPoint);
                    return RespBean.error(error.rspMsg());
                }
            } else {
                System.out.println("{}===============>错误信息");
                var6.printStackTrace();
                //未获取到error注解
                saveErrorLog(var6, var6.getCause().toString(), joinPoint);
                return RespBean.error("服务器错误");
            }
        }
    }

    private void saveErrorLog(Throwable e, String description, JoinPoint joinPoint) {
        try {
            String nameCreate = "anonymous";
            if (null != RequestVariable.getRequestData()
                    && null != RequestVariable.getRequestData().getUserId()) {
                nameCreate = RequestVariable.getRequestData().getUserId();
            }

            String throwable = "";
            if (e instanceof Exception) {
                throwable = getStackTrace((Exception) e);
            } else {
                throwable = e.toString();
            }
            errorLogService.saveErrorLog(description, getMethod(joinPoint).toString(), getParamData(joinPoint).toString()
                    , new Date(), throwable, nameCreate);
        } catch (Throwable throwable) {
            System.out.println("{}===============>日志保存错误");
        }
    }


    public boolean contains(Class<?>[] array, Class<?> target) {
        Class[] var3 = array;
        int var4 = array.length;
        for (int var5 = 0; var5 < var4; ++var5) {
            Class<?> aClass = var3[var5];
            if (aClass.isAssignableFrom(target)) {
                return true;
            }
        }
        return false;
    }


    public static Error getErrorData(JoinPoint joinPoint) throws Exception {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        return method.getAnnotation(Error.class);
    }

    public static Method getMethod(JoinPoint joinPoint) throws Exception {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        return signature.getMethod();
    }

    public static Map<String, Object> getParamData(JoinPoint joinPoint) throws Exception {
        Map<String, Object> param = new HashMap();
        Object[] paramValues = joinPoint.getArgs();
        String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();

        for (int i = 0; i < paramNames.length; ++i) {
            param.put(paramNames[i], paramValues[i]);
        }

        return param;
    }

    public static String getStackTrace(Exception e) {
        StringBuffer message = new StringBuffer();
        StackTraceElement[] exceptionStack = e.getStackTrace();
        message.append(e.toString());

        for (StackTraceElement ste : exceptionStack) {
            message.append("at " + ste);
        }
        return message.toString();
    }

}